package com.iwechat.adapter.mina;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.session.IoSessionConfig;
import org.apache.mina.filter.executor.ExecutorFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

import com.iwechat.adapter.mina.entity.PDU;

/**
 * NIOServer
 *
 *
 */
public class NioServer {
    private static final Logger         logger = LogManager.getLogger();
    private String                      serverName;
    private int                         port;
    private int                         idleTime;
    private NioSocketAcceptor           accepter;
    private NioHandlerAdapter           ioHandler;
    private DefaultIoFilterChainBuilder filterChain;
    private ExecutorService             poolService;

    /**
     * 初始化并启动
     */
    public void init() {
        logger.info("{}, startting...", this);

        accepter.setReuseAddress(true);
        IoSessionConfig config = accepter.getSessionConfig();
        config.setBothIdleTime(idleTime);
        config.setMinReadBufferSize(PDU.HEAD_LEN);

        accepter.setFilterChainBuilder(filterChain);
        accepter.setHandler(ioHandler);
        poolService = Executors.newCachedThreadPool();
        filterChain.addLast("executorFilter", new ExecutorFilter(poolService));

        try {
            accepter.bind(new InetSocketAddress(port));
            logger.info("{}, bind on port {}.", this, port);
        } catch (IOException e) {
            logger.error("{}, bind on port {} failed.", this, port);
            logger.error(e, e);
        }

    }

    /**
     * 停止服务
     *
     *
     */
    public void destroy() {
        accepter.unbind();
        accepter.dispose(false);
        poolService.shutdown();
        logger.info("{}, stoped.", this);
    }

    public NioSocketAcceptor getAccepter() {
        return accepter;
    }

    public DefaultIoFilterChainBuilder getFilterChain() {
        return filterChain;
    }

    public int getIdleTime() {
        return idleTime;
    }

    public NioHandlerAdapter getIoHandler() {
        return ioHandler;
    }

    public String getServerName() {
        return serverName;
    }

    public void setAccepter(NioSocketAcceptor accepter) {
        this.accepter = accepter;
    }

    public void setFilterChain(DefaultIoFilterChainBuilder filterChain) {
        this.filterChain = filterChain;
    }

    public void setIdleTime(int idleTime) {
        this.idleTime = idleTime;
    }

    public void setIoHandler(NioHandlerAdapter ioHandler) {
        this.ioHandler = ioHandler;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }

    /**
     * @param port
     *            the port to set
     */
    public void setPort(int port) {
        this.port = port;
    }

}
